/**
 * @file rtu.c
 * @brief this is a brief description
 * @details this is the detail description.
 * @author fulong 
 * @data 7/23/2014
 * @version 1.0
 * @par Copyright (c):
 * @par First build
 *     version: fulong 
 *     data: 7/23/2014
 */
#include "rtu.h"
#include "../ms_protocol/common.h"
#include "../mb_time_manage/mb_time.h"
#include "../../../lib/crc.h"
#include "../../../dev/uart.h"
#include "../../../hal/hal_uart.h"

#ifdef MODBUS_ENABLE
#ifdef MODBUS_RTU_MODE
typedef enum {
    SLAVE_ADDRESS_OFFSET = 0, /*!< 从机地址在帧的偏移量 */
    FUNCTION_CODE_OFFSET = 1, /*!< 功能码在帧的偏移量 */
    DATA_OFFSET = 2           /*!< 数据部分在帧的偏移量 */
}ADU_offect;

    #define START_STOP_TIME 3 //ms
    #define SLAVE_DEFAULT_TIMEOUT 2 //ms
    #define IS_TIMEOUT 1

    #define RTU_EXCEPT_ADU_MAX_LEN (RESPOND_ADU_LEST_LEN+2)

/*!< 记录当时的接收结束状态. */
uint8 rtu_receive_status;

extern mb_status_struct slave_mb_status;
extern receive_frame_struct slave_receive_frame;
extern uint8 slave_receiving_counter;

/*! \brief rtu操作模式初始化
 * \param
 * \retrun
 */
void rtu_mode_init(void)
{
    mb_time_manage_init();
    slave_mb_status.mb_status = 0;
    slave_mb_status.data_process_done = 0;
    rtu_receive_status = RTU_STOP;
    mb_set_rtu_timeout(START_STOP_TIME);
}
void rtu_receive(void)
{
    uint8 data_len, verifaction_offset;
    if (slave_mb_status.data_process_done == 0)
    {
        slave_mb_status.mb_adu->addr = slave_receive_frame.receive_frame[SLAVE_ADDRESS_OFFSET];
        slave_mb_status.mb_adu->mb_req_pdu.function_code = slave_receive_frame.receive_frame[FUNCTION_CODE_OFFSET];
        slave_mb_status.mb_adu->mb_req_pdu.request_data_len = slave_mb_status.mb_frame_len - 2 - 2;
        for (data_len = 0; data_len <  slave_mb_status.mb_adu->mb_req_pdu.request_data_len; data_len++)
        {

            slave_mb_status.mb_adu->mb_req_pdu.request_data[data_len] = slave_receive_frame.receive_frame[DATA_OFFSET + data_len];
        }
        verifaction_offset = data_len;
        slave_mb_status.mb_adu->verifaction_low8 = slave_receive_frame.receive_frame[DATA_OFFSET + verifaction_offset];
        slave_mb_status.mb_adu->verifaction_high8 = slave_receive_frame.receive_frame[DATA_OFFSET + verifaction_offset + 1];
        slave_mb_status.data_process_done = 1;
    }
}
void rtu_send(void)
{
}
uint8 rtu_adjust_verify(mb_adu_struct *mb_adu)
{
    uint16 verify;
    uint16 receive_verify;
    receive_verify = (mb_adu->verifaction_low8 + ((uint16)mb_adu->verifaction_high8 << 8));
    verify = get_crc_verify_num(slave_receive_frame.receive_frame, slave_receive_frame.frame_len - 2);
    if (verify == receive_verify)
    {
        return (VERIFY_SUCCESS);
    } else
    {
        return (VERIFY_FAIL);
    }
}
void rtu_normal_rsp(mb_rsp_pdu_struct *mb_rsp_pdu)
{
    uint8 send_normal_adu[NORMAL_ADU_MAX_LEN];
    uint16 crc_verify;
    uint8 i;
    if (NORMAL_ADU_MAX_LEN < (3 + 2 + mb_rsp_pdu->request_data_len))
    {
        return;
    }
    send_normal_adu[0] = SLAVE_ADDRESS;
    send_normal_adu[1] = mb_rsp_pdu->function_code;
    send_normal_adu[2] = mb_rsp_pdu->request_data_len;
    for (i = 0; i < mb_rsp_pdu->request_data_len; i++)
    {
        send_normal_adu[3 + i] = mb_rsp_pdu->response_data[i];
    }
    crc_verify = get_crc_verify_num(send_normal_adu, 3 + mb_rsp_pdu->request_data_len);
    send_normal_adu[3 + i] = crc_verify;
    send_normal_adu[3 + i + 1] = crc_verify >> 8;
    uart_send_string_with_len(send_normal_adu, 3 + 2 + mb_rsp_pdu->request_data_len);
}
void rtu_except_rsp(mb_excep_rsp_pdu_struct *mb_except_pdu)
{
    uint8 send_except_adu[RTU_EXCEPT_ADU_MAX_LEN];
    uint16 crc_verify;
    send_except_adu[0] = SLAVE_ADDRESS;
    send_except_adu[1] = mb_except_pdu->exception_function_code;
    send_except_adu[2] = mb_except_pdu->exception_code;
    crc_verify = get_crc_verify_num(send_except_adu, 3);
    send_except_adu[3] = crc_verify;
    send_except_adu[4] = (crc_verify >> 8);
    uart_send_string_with_len(send_except_adu, RTU_EXCEPT_ADU_MAX_LEN);
}
/*! \brief 接收帧数据,这个函数放在串口中断中,在接收过程中,会过滤掉开始与结束标识符.
 * \param data 串口数据入口
 * \retrun
 */
void rtu_receive_frame_function(const uint8 data)
{
    /*如果接收帧的长度大过能接收的最大程度，则出错，丢弃该帧*/
    if (slave_receiving_counter >= RECEIVE_MAX_LEN)
    {
        slave_receiving_counter = 0;
        return;
    }
    if (slave_receive_frame.receive_frame_done == 0)
    {
        if (RTU_START == rtu_receive_status)
        {
            /* 字符传输间超时，则丢弃该帧**/
            if (IS_TIMEOUT ==  mb_get_frame_char_timeout_status())
            {
                slave_receiving_counter = 0;
            }
            /* 如果没超时接收到下一个字符,则重置一下超时设定。**/
            mb_frame_char_timeout_clr();
            mb_set_frame_char_timeout(SLAVE_DEFAULT_TIMEOUT);
            mb_set_rtu_timeout(START_STOP_TIME);
            slave_receive_frame.receive_frame[slave_receiving_counter] = data;
            slave_receiving_counter++;
        }
    }
}
void rtu_time_hook(void)
{
    if (slave_receiving_counter != 0)
    {
        slave_receive_frame.receive_frame_done = 1;
        slave_receive_frame.frame_len = slave_receiving_counter;
        slave_receiving_counter  = 0;
        /*当接收完，就没必要算每个字符的接收间隔了*/
        mb_set_frame_char_timeout(0);
        mb_frame_char_timeout_clr();
        /*开始信号,需要slave_receive_frame处理完毕后,才会再次开启*/
        mb_set_rtu_timeout(0);
        return;
    }
}

#endif
#endif
